package com.kehutong.payfees.service;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.kehutong.common.util.Token;
import com.kehutong.payfees.util.BasicClient;
import com.kehutong.payfees.util.ExcelUtil;
import com.kehutong.payfees.util.JDBCUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.coraframework.converter.util.StringUtil;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.orm.util.Enums;
import org.coraframework.util.Objects;

import com.kehutong.common.errcode.Result;
import com.kehutong.payfees.entity.ChargeBill;
import com.kehutong.payfees.entity.ChargeBillItem;
import com.kehutong.payfees.entity.ChargeMediation;
import com.kehutong.payfees.enums.BillEnableState;
import com.kehutong.payfees.enums.BillPaidState;
import com.kehutong.payfees.enums.MediationType;

@WebService("/charge/lawyer/adjust")
public class ChargeLawyerMediationServiceImpl {

    @Inject
    private JdbcSession sqlSession;
    @Inject
    private BasicClient basicClient;

    public Page<ChargeBill> getChargeLawyerList(JSONObject jsonObject) {
        FindPage<ChargeBill> find = sqlSession.findPage(ChargeBill.class)
                .eq(jsonObject, "communityNo")
                .eq( "enableState", BillEnableState.ENABLE)
                .eq("paidState", BillPaidState.UNPAID)
                .like(jsonObject, "buildingName", "houseName")
                .eq("deleted", false)
                .eq("lawyerCharge", false)
                .order("communityNo", "DESC")
                .order("buildingName", "ASC")
                .order("unitName", "ASC")
                .order("floorName", "ASC")
                .order("houseName", "ASC")
                .order("billDateFrom", "ASC")
                .order("shouldPayDate", "ASC")
                .order("id", "ASC")
                .page(jsonObject);

        // 应付日期 包含在查询范围内

        if (StringUtil.isNotBlank(jsonObject.getString("shouldPayDateFrom"))) {
            find.maxEq("shouldPayDate", jsonObject.get("shouldPayDateFrom"));
        }
        if (StringUtil.isNotBlank(jsonObject.getString("shouldPayDateTo"))) {
            find.minEq("shouldPayDate", jsonObject.get("shouldPayDateTo"));
        }
        // 账单周期 查出与查询条件范围有交集的
        if (StringUtil.isNotBlank(jsonObject.getString("billDateTo"))) {
            find.minEq("billDateFrom", jsonObject.get("billDateTo"));
        }
        if (StringUtil.isNotBlank(jsonObject.getString("billDateFrom"))) {
            find.maxEq("billDateTo", jsonObject.get("billDateFrom"));
        }

        return find.exe();
    }

    public void saveLawyerCharge(Token token, JSONObject jsonObject) throws Exception {
        JSONArray checkedList = jsonObject.getJSONArray("checkedList");
        List<ChargeBill> chargeBills = sqlSession.findArray(ChargeBill.class)
                .in("id", checkedList).exe();

        Map<String, List<ChargeBill>> collectChargeBill = chargeBills.stream().collect(Collectors.groupingBy(ChargeBill::getHouseNo));
        for (String k :collectChargeBill.keySet()) {
            List<ChargeBill> v = collectChargeBill.get(k);

            ChargeMediation chargeMediation = Pool.newInstance(ChargeMediation.class);
            ChargeBill chargeBill = v.get(0);
            setBasicChargeMediation(chargeMediation, chargeBill, jsonObject);

            JSONObject house = basicClient.getHouseById(token, k);
            chargeMediation.setRespondent(house.getString("ownerName"));
            chargeMediation.setRespondentMobile(house.getString("ownerMobile"));
            chargeMediation.setRespondentNo(house.getString("ownerNo"));

            BigDecimal oweAmount = new BigDecimal(0);
            List<String> chargeBillIds = new ArrayList<>();
            for (ChargeBill item : v) {
                oweAmount = oweAmount.add(item.getTotal());
                chargeBillIds.add(item.getId());
                if (Objects.isNull(chargeMediation.getBillDateFrom())) {
                    chargeMediation.setBillDateFrom(item.getBillDateFrom());
                    chargeMediation.setBillDateTo(item.getBillDateTo());
                    continue;
                }

                if (chargeMediation.getBillDateFrom().isAfter(item.getBillDateFrom())) {
                    chargeMediation.setBillDateFrom(item.getBillDateFrom());
                }
                if (chargeMediation.getBillDateTo().isBefore(item.getBillDateTo())) {
                    chargeMediation.setBillDateTo(item.getBillDateTo());
                }
            }
            chargeMediation.setOweAmount(oweAmount);
            chargeMediation.setChargeBillIds(chargeBillIds);
            sqlSession.insert(chargeMediation);

            chargeBills.forEach(item -> item.setLawyerCharge(true));
            sqlSession.updateById(chargeBills);
        }
    }

    public Page<ChargeMediation> getLawyerChargePage(Token token, JSONObject jsonObject) throws Exception {
        FindPage<ChargeMediation> findPage = sqlSession.findPage(ChargeMediation.class)
                .like(jsonObject, "companyName", "communityName", "houseName", "respondent", "disputedPoints")
                .order("createTime", "desc");

        JDBCUtil.between(jsonObject, findPage,"createTime");

        if (Objects.nonEmpty(jsonObject.getString("minOweAmount"))) {
            findPage .max("oweAmount", jsonObject.getString("minOweAmount"));
        }
        if (Objects.nonEmpty(jsonObject.getString("maxOweAmount"))) {
            findPage .min("oweAmount", jsonObject.getString("maxOweAmount"));
        }
        if (!Objects.equal("0",jsonObject.getString("mediationType"))) {
            findPage.eq("mediationStatus", Enums.getEnum(MediationType.class, jsonObject.getString("mediationType")));
        }
        if (Objects.nonEmpty(jsonObject.getString("handlerNo"))) {
            findPage .eq("handlerNo", jsonObject.getString("handlerNo"));
        }

        Page<ChargeMediation> page = findPage.page(jsonObject).exe();
        List<ChargeMediation> list = page.getList();
        for (ChargeMediation item: list) {
            JSONObject community = basicClient.getCommunityById(token, item.getCommunityNo());
            if (Objects.nonNull(community)) {
                item.setProvincesCities(community.getString("area_ids"));
            }
        }

        return findPage.page(jsonObject).exe();
    }

    public List<ChargeBill> getLawyerChargeDetail(String id) {
        ChargeMediation chargeMediation = Pool.get(ChargeMediation.class, id);
        if (chargeMediation == null) {
            return null;
        }

        List<String> chargeBillIds = chargeMediation.getChargeBillIds();
        List<ChargeBill> chargeBillList = sqlSession.findArray(ChargeBill.class)
                .in("id", chargeBillIds).exe();
        chargeBillList.forEach(chargeBill -> {
            List<ChargeBillItem> items = sqlSession.findArray(ChargeBillItem.class)
                    .eq("billNo", chargeBill.getId())
                    .exe();
            chargeBill.setBillItems(items);
        });

        return chargeBillList;
    }

    public void updateLawyerCharge(JSONObject jsonObject) {
        ChargeMediation chargeMediation = Pool.get(ChargeMediation.class, jsonObject.getString("id"));
        if (Objects.nonEmpty(jsonObject.getString("employeeNo"))) {
            chargeMediation.setEmployeeNo(jsonObject.getString("employeeNo"));
            chargeMediation.setEmployeeName(jsonObject.getString("employeeName"));
            chargeMediation.setMobile(jsonObject.getString("mobile"));
        }
        chargeMediation.setDisputedPoints(jsonObject.getString("disputedPoints"));
        sqlSession.updateById(chargeMediation);
    }

    public Page<ChargeBill> getLawyerChargeDetailById(JSONObject jsonObject) {
        ChargeMediation chargeMediation = Pool.get(ChargeMediation.class, jsonObject.getString("id"));
        return sqlSession.findPage(ChargeBill.class)
                .in("id", chargeMediation.getChargeBillIds())
                .order("communityNo", "DESC")
                .order("buildingName", "ASC")
                .order("unitName", "ASC")
                .order("floorName", "ASC")
                .order("houseName", "ASC")
                .order("billDateFrom", "ASC")
                .order("shouldPayDate", "ASC")
                .order("id", "ASC")
                .page(jsonObject)
                .exe();
    }

    public File exportById(JSONObject jsonObject) throws IOException {
        ChargeMediation chargeMediation = Pool.get(ChargeMediation.class, jsonObject.getString("id"));
        List<ChargeBill> chargeBillList = sqlSession.findArray(ChargeBill.class)
                .in("id", chargeMediation.getChargeBillIds())
                .order("communityNo", "DESC")
                .order("buildingName", "ASC")
                .order("unitName", "ASC")
                .order("floorName", "ASC")
                .order("houseName", "ASC")
                .order("billDateFrom", "ASC")
                .order("shouldPayDate", "ASC")
                .order("id", "ASC")
                .exe();

        Workbook wb = exportChargeBill(chargeBillList);
        return ExcelUtil.writeXlsFile(wb, "催缴的缴费列表", ".xls");
    }

    public Map<String, Object> getLawyerChargeById(Token token, String id) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        ChargeMediation chargeMediation = Pool.get(ChargeMediation.class, id);
        resultMap.put("chargeMediation", chargeMediation);

//        List<CustomerHouse> customerHouseList = SignJDBCSession.findArray(CustomerHouse.class)
//                .eq("houseId", chargeMediation.getHouseNo())
//                .eq("userType", CustomerType.OWNER)
//                .eq("deleted", false).exe();
        List<String> sendRespondentNoList = new ArrayList<>();
//        if (Objects.nonEmpty(customerHouseList)) {
//            customerHouseList.forEach(customerHouse -> {
//                sendRespondentNoList.add(customerHouse.getContactId());
//            });
//        }
        chargeMediation.setSendRespondentNoList(sendRespondentNoList);

        JSONObject data = basicClient.getCommunityById(token, chargeMediation.getCommunityNo());
        resultMap.put("community", data);
        return resultMap;
    }

    public Object changeMediationStatusById(JSONObject jsonObject) {
        ChargeMediation chargeMediation = Pool.get(ChargeMediation.class, jsonObject.getString("id"));
        if (Objects.isNull(chargeMediation)) {
            return Result.error(-1, "对象不存在！");
        }
        chargeMediation.setMediationStatus(Enums.getEnum(MediationType.class, jsonObject.getString("mediationStatus")));
        sqlSession.updateById(chargeMediation);
        return Result.success();
    }

    public void updateLawyerChargeHandler(JSONObject jsonObject) {
        ChargeMediation chargeMediation = Pool.get(ChargeMediation.class, jsonObject.getString("id"));
        if (Objects.nonNull(chargeMediation)) {
            chargeMediation.setHandlerNo(jsonObject.getString("handlerNo"));
            chargeMediation.setHandler(jsonObject.getString("handler"));
            chargeMediation.setHandlerMobile(jsonObject.getString("handlerMobile"));
            sqlSession.updateById(chargeMediation);
        }
    }

    private void setBasicChargeMediation(ChargeMediation chargeMediation, ChargeBill chargeBill, JSONObject jsonObject) {
        chargeMediation.setEmployeeName(jsonObject.getString("employeeName"));
        chargeMediation.setEmployeeNo(jsonObject.getString("employeeNo"));
        chargeMediation.setMobile(jsonObject.getString("mobile"));

        chargeMediation.setCommunityNo(chargeBill.getCommunityNo());
        chargeMediation.setCommunityName(chargeBill.getCommunityName());
        chargeMediation.setBuildingNo(chargeBill.getBuildingNo());
        chargeMediation.setBuildingName(chargeBill.getBuildingName());
        chargeMediation.setUnitName(chargeBill.getUnitName());
        chargeMediation.setHouseNo(chargeBill.getHouseNo());
        chargeMediation.setHouseName(chargeBill.getHouseName());
    }

    public void updateLawyerChargeHandlerMore(Token token, JSONObject jsonObject) throws Exception {
        JSONArray checkedList = jsonObject.getJSONArray("checkedList");
        List<ChargeMediation> chargeMediationList = sqlSession.findArray(ChargeMediation.class)
                .in("id", checkedList).exe();
        if (Objects.nonEmpty(chargeMediationList)) {
            for (ChargeMediation chargeMediation: chargeMediationList) {
                chargeMediation.setHandlerNo(jsonObject.getString("handlerNo"));
                chargeMediation.setHandler(jsonObject.getString("handler"));
                chargeMediation.setHandlerMobile(jsonObject.getString("handlerMobile"));
                //TODO 获取处理人的企业编号待确认
                JSONObject handlerNo = basicClient.getEmployeeById(token, jsonObject.getString("handlerNo"));
                chargeMediation.setHandlerCompanyNo(token.getCompanyNo());
            }
        }
        sqlSession.updateById(chargeMediationList);
    }

    private Workbook exportChargeBill(List<ChargeBill> chargeBillList) {

        // 生成模板文件
        HSSFWorkbook wb = new HSSFWorkbook();

        Sheet sheet = wb.createSheet();
        Row headerRow = sheet.createRow(0);
        int headerCellNum = 0;
        String[] chargeUserInstrument = {"小区", "楼栋/区域", "房屋信息", "账单周期", "应付款日", "缴费状态", "缴费金额"};
        for (String s : chargeUserInstrument) {
            Cell cell = headerRow.createCell(headerCellNum++);
            cell.setCellValue(s);
        }

        int cellNum = 0;
        for (int i = 0; i < chargeBillList.size(); i++) {
            Row row = sheet.createRow(i + 1);
            cellNum = 0;
            ChargeBill chargeBill = chargeBillList.get(i);
            row.createCell(cellNum++).setCellValue(chargeBill.getCommunityName());
            row.createCell(cellNum++).setCellValue(chargeBill.getBuildingName());
            row.createCell(cellNum++).setCellValue(chargeBill.getUnitName() + chargeBill.getFloorName() + chargeBill.getHouseName());
            row.createCell(cellNum++).setCellValue(chargeBill.getBillDateFrom() + " 至 " + chargeBill.getBillDateTo());
            row.createCell(cellNum++).setCellValue(chargeBill.getShouldPayDate().toString());
            row.createCell(cellNum++).setCellValue(chargeBill.getPaidState().getDesc());
            row.createCell(cellNum++).setCellValue(chargeBill.getTotal().toString());
        }

        // 自动列宽
        for (int i = 0; i < cellNum; i++) {
            if (i == 0) {
                // id列不调整
                continue;
            }
            // 自动列宽
            ExcelUtil.autoSizeColumn(sheet, i);
        }
        return wb;
    }
}
